#pragma once
#include<iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include"log.hpp"
#include <cstring>
#include"inet_addr.hpp"

class Socket{
    public:
       Socket(){};
       virtual ~Socket(){};
       virtual bool Bind(uint16_t port)=0;
       virtual bool Listen()=0;
       virtual bool Connect(const std::string& ip,uint16_t port)=0;
       virtual bool Send(const std::string& msg)=0;
       virtual int Recv(std::string& msg)=0;
};
class TcpSocket:public Socket{
    public:
        TcpSocket(uint16_t port){
            _sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if(_sockfd==-1){
                LOG(ly::LogLevel::ERROR)<<"创建套接字失败"<<"\n";
                return;
            }
            LOG(ly::LogLevel::INFO)<<"创建套接字成功"<<"\n";
        }
        TcpSocket(int fd):_sockfd(fd){
        }
        virtual ~TcpSocket(){
            if(_sockfd!=-1){
                ::close(_sockfd);
            }
        }
        bool Bind(uint16_t port){
            sockaddr_in addr;
            memset(&addr,0,sizeof(addr));
            addr.sin_family=AF_INET;
            addr.sin_addr.s_addr=INADDR_ANY;
            addr.sin_port=htons(port);
            if(bind(_sockfd,(sockaddr*)&addr,sizeof(addr))==-1){
                LOG(ly::LogLevel::ERROR)<<"绑定失败"<<"\n";
                close(_sockfd);
                return false;
            }
            LOG(ly::LogLevel::INFO)<<"绑定成功"<<"\n";
            return true;
        }
        bool Listen(){
            if(listen(_sockfd,10)==-1){
                LOG(ly::LogLevel::ERROR)<<"监听失败"<<"\n";
                close(_sockfd);
                return false;
            }
            LOG(ly::LogLevel::INFO)<<"监听成功"<<"\n";
            return true;
        }
        int Accept(InetAddr* client_addr){
            sockaddr_in clientaddr;
            socklen_t addrlen=sizeof(clientaddr);
            int clientfd=accept(_sockfd,(sockaddr*)&clientaddr,&addrlen);
            if(clientfd==-1){
                LOG(ly::LogLevel::ERROR)<<"接受失败"<<"\n";
                return -1;
            }
            client_addr->SetAddr(clientaddr);
            LOG(ly::LogLevel::INFO)<<"接受成功"<<"\n";
            return clientfd;
        }
        bool Connect(const std::string& ip,uint16_t port){
            struct sockaddr_in serveraddr;
            memset(&serveraddr,0,sizeof(serveraddr));
            serveraddr.sin_family=AF_INET;
            serveraddr.sin_port=htons(port);
            if(inet_aton(ip.c_str(),&serveraddr.sin_addr)==0){
                LOG(ly::LogLevel::ERROR)<<"地址转换失败"<<"\n";
                return false;
            }
            if(connect(_sockfd,(sockaddr*)&serveraddr,sizeof(serveraddr))==-1){
                LOG(ly::LogLevel::ERROR)<<"连接失败"<<"\n";
                return false;
            }
            LOG(ly::LogLevel::INFO)<<"连接成功"<<"\n";
            return true;
        }
        bool Send(const std::string& msg){
            //write(_sockfd,msg.c_str(),msg.length());
            //std::cout<<msg<<std::endl;
            if(send(_sockfd,msg.c_str(),msg.length(),0)==-1){
                LOG(ly::LogLevel::ERROR)<<"发送失败"<<"\n";
                close(_sockfd);
                return false;
            }
            return true;
        }
        int Recv(std::string& msg){
            char buffer[4096];
            memset(buffer,0,sizeof(buffer));
            //read(_sockfd,buffer,sizeof(buffer)-1);
            int n=recv(_sockfd,buffer,sizeof(buffer)-1,0);
            if(n==-1){
                // 处理错误：区分可恢复错误和致命错误
                int err = errno;
                if (err == EINTR) {
                    // 被信号中断（临时错误），可重试
                    LOG(ly::LogLevel::WARNING) << "recv被信号中断，尝试重试" << "\n";
                    return Recv(msg);  // 递归重试
                } else if (err == ECONNRESET || err == EPIPE) {
                    // 连接被重置或对方已关闭（致命错误）
                    LOG(ly::LogLevel::ERROR) << "接收失败：连接已断开，错误码=" << err << "\n";
                    close(_sockfd);
                    _sockfd = -1;  // 标记套接字已关闭
                    exit(1);
                } else {
                    // 其他错误（如EAGAIN非阻塞模式）
                    LOG(ly::LogLevel::ERROR) << "接收错误，错误码=" << err << "\n";
                    return -1;  // 不关闭套接字，由上层决定是否重试
                }
                LOG(ly::LogLevel::ERROR)<<"接收失败"<<"\n";
                close(_sockfd);
                exit(1);
            }
            msg.clear();//为什么不用msg=buffer呢？在自定义协议中，sep="\r\n"，导致buffer中的信息不能完全到达msg中，string
            //的构造函数中会一第一个
            for(int i=0;i<n;i++){
                msg.push_back(buffer[i]);
            }
            return n;
        }
        int GetFd(){
            return _sockfd;
        }
    private:
        int _sockfd;
};